




// #include "iot_node.h"




#ifndef __IOT_NODE_H__                        
#define __IOT_NODE_H__


#include "stdint.h"
#include  "iotv30_config.h"

//#include  "StreepLamp.h"

#include "dev_manager.h"
#include "iot_message.pb.h"


#define   NODE_MAC_UINT64_ENABLE      (0x01)   //////是否使用64bits 格式的mac地址



#define     NODE_ID_LEN    (0x6U)     ///节点MAC地址的长度
#define     LINK_ID_LEN    (0x6U)     ///转发节点MAC地址的长度




//最大的节点个数   
//#define   NODE_NUM_MAX    (16U)   //255U-----空间不够
//#define   NODE_NUM_MAX    (128U)   //255U-----空间不够//Program Size: Code=141348 RO-data=7304 RW-data=2744 ZI-data=87280 
#define   NODE_NUM_MAX    (255U)   //255U-----空间不够//Program Size: Code=141348 RO-data=7304 RW-data=2744 ZI-data=88552 

//#define   NODE_CFG_COM_LEN              (9)   //每个节点通信参数的最大空间
//#define   NODE_CFG_PER_FLASH_LEN        (10)   //每个节点参数占用flash的最大空间

//#define   NODE_CFG_MAP_MAX        ( NODE_CFG_PER_FLASH_LEN * NODE_NUM_MAX ) //所有节点参数的最大空间



#define   NODE_CFG_COM_LEN              (sizeof(iot_NodeConfig_st))   //每个节点通信参数的最大空间
#define   NODE_CFG_PER_FLASH_LEN        ( sizeof(iot_NodeCore_st) )   //每个节点参数占用flash的最大空间
#define   NODE_CFG_MAP_MAX              ( NODE_CFG_PER_FLASH_LEN * NODE_NUM_MAX ) //所有节点参数的最大空间





#define    NODE_CREATE_DEFAULT_GROUP    (0x01)   //自动生成白名单的节点默认组号为1 




#pragma pack(1)

//---配置节点信息----------


typedef union
{
	struct{	
		
	  uint8_t white_name_added        :1;	  //添加白名单节点---1:添加完成
	  uint8_t white_name_del          :1;	  //删除白名单节点---1:需要删除		
	  uint8_t group_added             :1;	  //添加节点组号-----1:添加完成
	  uint8_t group_del               :1;		//删除节点组号-----1:需要删除	

	  uint8_t online                  :1;	  //节点在线标志-----1:在线，0:离线，
		
	  uint8_t set_node_rtc_done       :1;	  //完成设置节点RTC标志-----1:校时完成	
	  uint8_t update_done             :1;	  //节点升级完成标志--------1:升级完成			
		
			
	 uint8_t res            :1;  
		
	}bit;
	
  uint8_t all;

} Lamp_NodeCfgFlags_u;

#pragma pack()






// #define    NODE_CFG_NUM_MAX       (255)     //最大配置的节点数
// extern SubDevice  Iot_NodeCfg[NODE_CFG_NUM_MAX];



//#define DEV_MAX_NUM          (255)      /////拓扑节点的总数

#define DEV_CAT1_LAMP        (0xFFFF)

/////-----设备类型----
//#define   DEV_LIQUID_TYPE     (0xD000)     //液位传感器（D006H） 


// "D0H
// (传感器)"	00H	温湿度传感器
// 	01H	烟雾传感器 smoke
// 	02H	水浸传感器
// 	03H	电池传感器
// 	04H	门禁传感器
// 	5H	空调控制器
// 	6H	油位传感器
// 	7H	油机传感器
// 	8H	交流电传感器
// 	9H	直流电传感器
// 	0AH	
		

typedef enum{

    IOT_SENSOR_temper_humidity = 0xD000,//temperature and humidity 
    IOT_SENSOR_smoke,
    IOT_SENSOR_water,
    IOT_SENSOR_battery,
    IOT_SENSOR_dido,        //door 门禁传感器
    IOT_SENSOR_air_cond,    //air-conditioning Air conditioner--- HVAC是Heating, Ventilation and Air Conditioning  
    IOT_SENSOR_liquid,      // 0xD006H	油位传感器
    IOT_SENSOR_generator,   // oil engine     ///07H	油机传感器 --IOT_SENSOR_engine----

    IOT_SENSOR_ac_meter ,
    IOT_SENSOR_dc_meter ,

}  iot_node_dev_type_e;




/*-----------------------------------------------------------------------------------------------------------------

7.3.1 设备物模型定义
7.3.1.1子设备（拓扑）物模型
message SubDevice {
    uint32 sub_uid=1;
    uint32 sub_type=2;
    uint32 group_num=3;
    uint32 channel=4;
    uint64 sub_mac=5;
    uint32 link=6;
    uint64 link_mac=7;
}
编号	字段	名称	说明
1	sub_uid	子设备ID	子设备唯一ID（取值范围：1~65535）
{平台自动生成，与设备类型绑定，下发给网关，网关需要保存}
2	sub_type	子设备类型	用于区分不同类型的设备（见附录A）

3	group_num	分组号	取值范围：1~255；注意：组号不能为0。
为了方便同时控制多个子设备又不是广播控制时使用。
4	channel	通信方式 /
通道号	0：PLC
1~7：485
1：485I (第一路485)
2：485II (第二路485)
8：蓝牙
5	sub_mac	子设备地址	设备通讯地址码（除整数地址外，其它设备地址码，都是高字节在前，低字节在后）
根据子设备类型不同表示的含义也不同。
说明如下：
485通讯，地址码为485地址（整数）；
PLC通讯，地址码为PLC节点ID（长度6字节）。
6	link	转接终端
通信方式	二级转接子设备，例如PLC转485。
0：转LED
1~7：转485
1：485I (第一路485)
2：485II (第二路485)
8：转蓝牙  
7	link_mac	转接终端
设备地址	转接终端设备地址码（除整数地址外，其它设备地址码，都是高字节在前，低字节在后）
根据转接终端通信方式不同表示的含义也不同。
说明如下：
0 转LED，地址码为LED灯号（>0有效）；
1~7 转485，地址码为485地址（整数）；
8 转蓝牙，地址码为蓝牙地址（6字节）；



// 设备物模型定义
message SubDevice {
    uint32 sub_uid=1;
    uint32 sub_type=2;
    uint32 group_num=3;
    uint32 channel=4;
    uint64 sub_mac=5;
    uint32 link=6;
    uint64 link_mac=7;
}
message IotModel {
    uint32 iot_id=1;
    uint64 value=2;
    bytes values=3;
}
message SubIotData {
    uint32 sub_uid=1;
    OnlineState state=2;
    repeated IotModel props=3;
}

----------------------------------------------------------------------------------------------------------------*/


// 0：PLC
// 1~7：485
// 1：485I (第一路485)
// 2：485II (第二路485)
// 8：蓝牙

// typedef enum{
//     dev_chan_plc = 0,
//     dev_chan_485_1 = 1,
//     dev_chan_485_2,
//     dev_chan_485_3,
//     dev_chan_485_4,
//     dev_chan_485_5,
//     dev_chan_485_6,
//     dev_chan_485_7,

//     dev_chan_ble = 8,
//     dev_chan_cat1 = 9,
// }dev_chan_e;


#pragma pack(1)

/* 设备物模型定义 ----------------------------------------------------------------------------------------------------------------
typedef struct _SubDevice {
    uint32_t sub_uid;
    uint32_t sub_type;
    uint32_t group_num;
    uint32_t channel;
    uint64_t sub_mac;
    uint32_t link;
    uint64_t link_mac;
} SubDevice;

----------------------------------------------------------------------------------------------------------------*/
#define  IOT_NODE_DEV_NAME_STR_LEN (32U)

typedef struct{
    uint16_t sub_uid ;     //id---sub_uid	子设备ID	子设备唯一ID（取值范围：1~65535）{平台自动生成，与设备类型绑定，下发给网关，网关需要保存}
    iot_node_dev_type_e node_type;    //type sub_type 子设备类型	用于区分不同类型的设备（见附录A）
    uint8_t  group;        //取值范围：1~255；注意：组号不能为0

#if !NODE_MAC_UINT64_ENABLE    
    uint8_t sub_mac[NODE_ID_LEN];         //设备通讯地址码-----sub_mac[0]为最低位
    uint8_t link_mac[LINK_ID_LEN];        //转接终端设备地址码----link_mac[0]为最低位
#endif

    dev_chan_e channel;        //通信方式 /通道号  channel
    dev_chan_e link_channel;   //转接终端 通信方式

#if NODE_MAC_UINT64_ENABLE    
    uint64_t sub_mac;         //设备通讯地址码
    uint64_t link_mac;        //转接终端设备地址码
#endif

    char   dev_name_str[IOT_NODE_DEV_NAME_STR_LEN];   
}  iot_NodeConfig_st ;    ///dev_topo_t;





//上行协议 5.4.10  B :下发节点 95H（新版本） 通信数据结构

//节点UID
//节点的组号： 1~255；注意：组号不能为0
//设备类型(见附录A)
//节点编号（1~255）

// typedef		struct         
// {			

// 	uint8_t      ID[NODE_ID_LEN];	//节点的物理地址----大端存储-----
// 	uint8_t      Group;  //组号		
// 	uint8_t      Type;   //节点类型	
// 	uint8_t      Nb;     //ID映射表的编号,从1开始，但是不一定是按顺序的--节点编号（1~255）
		
// } NodeConfig_st; //3 +6=9





//对应上行下发节点 95H（新版本）的通信数据结构
typedef	 union 
{
	uint8_t         Buffer[NODE_CFG_COM_LEN];
	
    iot_NodeConfig_st   Node; //3 +6=9
				
} iot_NodeCfg_Com_u; ////3 +6=9




typedef		struct         
{			
  iot_NodeConfig_st        Config;
  Lamp_NodeCfgFlags_u      Flag;    
		
} iot_NodeCore_st; //9+1=10



////----服务器配置到集中器 的节点的参数----

typedef	 union 
{
	uint8_t         Buffer[NODE_CFG_MAP_MAX];
	
    iot_NodeCore_st     Node[NODE_NUM_MAX]; //10
				
} iot_NodeConfigObj_u; //=9*255=2295/1024=2.24k   === =10*255=2550/1024=2.49k



#pragma pack()



extern iot_NodeConfigObj_u   iot_NodeConfigObj;



void iot_Node_Init(void);


void iot_Node_Test(void);



// 主动轮询节点的周期时间--这个需要小于等于-#define  TLV_ReportPeriod_sec   ( 2*60 )   -否则意义不大  
void iot_Node_Test_tick_min(void);

// (liquid_config_t*)pcfg ;
void iot_Node_WriteSensor(void* pcfg);

//dpid
// 0x0601	液位报警使能	 data_type=3
// 0x0604	液位过低阈值     data_type=4
// 0x0605	液位过高阈值     data_type=4
// 0x0486	温度过低阈值     data_type=4
// 0x0487	温度过高阈值     data_type=4
//1,0x12, 3 or 4 
uint8_t iot_Node_WriteSensor_one( uint8_t dev_addr, uint8_t chan,uint8_t data_type, uint16_t dpid, uint32_t value);



void iot_Node_ParamSaveFlashEnable(void);

//保存白名单到PLC CCO 
void iot_Node_ParamSaveToPLC(void);

void iot_Node_UpdateParamProcess(void);


uint8_t  iot_Node_GetNum(void);
void     iot_Node_SetNum(uint8_t num);


//返回值非0，表示查找成功；返回值0，表示查找失败，不存在该编号
uint8_t iot_Node_GetIndex( uint16_t sub_uid, uint8_t* index );


/**
 * @brief 
 *    ////重新计数------每次只发送 MAX_NUM_IN_PACKET 个节点的数据-------
     ////当前是连包发送，没有分帧发送处理，
 * @param  idx 配置节点的下标索引
 * @return NodeConfig_st* 返回配置节点的数据结构指针, ==NULL 表示查找失败 ，  !NULL 表示查找成功
 */

iot_NodeConfig_st* iot_Node_Get_topoinfo(uint8_t idx);




//添加单个节点
//void AddOneNode(uint8_t* node_id )  =====原来旧的函数名
//先查找有没有相同的ID节点，有则覆盖，没有则新增
void iot_Node_Add(void* nod  );




#if NODE_MAC_UINT64_ENABLE    

//返回值非0，表示查找成功；返回值0，表示查找失败，不存在该编号
uint8_t iot_Node_GetIndexWithId( uint64_t id, uint8_t* index );

//删除单个节点
void iot_Node_Delete(uint64_t node_id );


#else
//返回值非0，表示查找成功；返回值0，表示查找失败，不存在该编号
uint8_t iot_Node_GetIndexWithId( uint8_t* id, uint8_t* index );

//删除单个节点
void iot_Node_Delete(uint8_t* node_id  );


#endif



//删除组节点
void iot_Node_DeleteGroup(uint8_t group);
void iot_Node_DeleteGroup_ByType(uint8_t group,uint16_t node_type);
//删除某个类型的节点
void iot_Node_DeleteType(uint16_t node_type);



//清空所有配置节点
void iot_Node_Clear(void );


//历史原因---保留旧的函数名---保持兼容-------
#define  CreateNode   iot_Node_Create

//开放性组网
void iot_Node_Create(void);




//针对PLC节点数据
void iot_Node_Destroy(void);

//////mac_array[0]为最低位
#define dev_mac_u64(mac_array) ((uint64_t)mac_array[0] | (uint64_t)mac_array[1] << 8 | (uint64_t)mac_array[2] << 16 | (uint64_t)mac_array[3] << 24 | (uint64_t)mac_array[4] << 32 | (uint64_t)mac_array[5] << 40)


uint64_t iot_mac_to_uint64(uint8_t*  mac );


#endif    //  __IOT_NODE_H__













